/* 
 * EK
 * 
 * Enrichment Kit @ek.version@ (http://enrichmentkit.com)
 * Copyright (c) 2008 Pink Hominid
 * Licensed under terms of the MIT License (LICENSE.txt)
 * 
 * IE 6.0+, FF 1.5+ Tested
 * 
 * Convention >> http://javascript.crockford.com/code.html
 */

if ( typeof window.EK == "undefined" ) { 

    /**
     * EK namespace & general utils
     */
    var EK = {
        debugOn: false,
        
	    /**
	     * Only Mozilla supports Array indexOf, here it is for the others...
	     * Returns the first index number at which the specified element can be
	     * found in the array. Returns -1 if the element is not present.
	     * 
	     * @param {Array} anArray The array to search
	     * @param {Object} objectToFind The object you are searching for
	     * @return {Number} The index of the Object in the Array or -1
	     */
	    arrayIndexOf : function(anArray, objectToFind) {
	        var indexOfObjectToFind = -1;
	        for (var idx=0; idx < anArray.length; idx++) {
	            if (anArray[idx] === objectToFind) { 
	                indexOfObjectToFind = idx;
	                break;
	            }
	        }
	        return indexOfObjectToFind;
	    },
		
        /**
         * Browser type and version
         * Thanks jQuery :)
         */
        browser: {
            version: (navigator.userAgent.match(
                /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/i) || [])[1],
            msie: /msie/i.test(navigator.userAgent) &&
                !(/opera/i.test(navigator.userAgent)),
            mozilla: /mozilla/i.test(navigator.userAgent) &&
                !(/(compatible|webkit)/i.test(navigator.userAgent))
        },
        
        /**
         * Writes an object to the Firebug debug console, if it exists. 
         * @param obj {Object} The object to write to the console
         */
        debug: function (obj) {
            if (this.debugOn && window.console && console.debug) { console.debug(obj); }
        },

        /* thanks overset dev sandbox */
        deepObjCopy: function (dupeObj) {
            if (dupeObj === null || dupeObj === undefined) { return dupeObj; }
            var retObj = {};
            if (typeof(dupeObj) == 'object') {
                if (typeof(dupeObj.length) !== 'undefined' &&
                   (dupeObj.length === 0 ||
                    typeof(dupeObj[dupeObj.length - 1]) !== 'undefined')) {

                    retObj = [];
                }
                for (var objInd in dupeObj) {
                    if (typeof(dupeObj[objInd]) == 'undefined') {
                        retObj[objInd] = undefined;    
                    } else if (dupeObj[objInd] === null) {
                        retObj[objInd] = null;
                    } else if (dupeObj[objInd].constructor == Date) {
                        retObj[objInd] = new Date(dupeObj[objInd].toString());
                    } else if (typeof(dupeObj[objInd]) == 'object') {
                        retObj[objInd] = this.deepObjCopy(dupeObj[objInd]);
                    } else if (typeof(dupeObj[objInd]) == 'string') {
                        retObj[objInd] = dupeObj[objInd];
                    } else if (typeof(dupeObj[objInd]) == 'number') {
                        retObj[objInd] = dupeObj[objInd];
                    } else if (typeof(dupeObj[objInd]) == 'boolean') {
                        ((dupeObj[objInd] === true) ? retObj[objInd] = true : retObj[objInd] = false);
                    }
                }
            }
            return retObj;
        },
        
        /**
         * Writes an object to the Firebug error console, if it exists. 
         * @param obj {Object} The object to write to the console
         */
        error: function (obj) {
            if (window.console && console.error) { console.error(obj); }
        },
		
        /**
         * Thanks Prototype :)
         * @param html {Object}
         */
        escapeHtml: function (html) {
            var div = document.createElement('div');
            var text = document.createTextNode(html);
            div.appendChild(text);
            return div.innerHTML;
        },

        /**
         * Simple inheritance. Thanks jQuery :)
         * @param target {Object} The Object to extend
         * @param obj1 {Object} An Object to extend with
         * @param objN {Object} More Objects to extend with
         */
		extend: function (/*target, obj1, [objN]*/) {
			var target = arguments[0] || {}, a = 1, al = arguments.length, prop;
		
			for ( ; a < al; a++ ) {
				// Only deal with non-null/undefined values
				if ( (prop = arguments[a]) !== null ) {
					// Extend the base object
					for ( var i in prop ) {
						// Prevent never-ending loop
						if ( target == prop[i] ) { continue; }
		
						// Don't bring in undefined values
						if ( prop[i] !== undefined ) { target[i] = prop[i]; }
					}
					// if one of the Objects is an Array bring length over
					// manually since 'in' iterating doesn't pick it up
					if (prop.constructor == Array) {
						target.length = prop.length;
					}
                }
            }
			// Return the modified object
			return target;
		},
        
        /**
         * Implements Mozilla's Function name property for IE
         * @param {Object} fn
         */
        functionName: function (fn) {
            if (this.browser.mozilla) {
                return fn.name;				
            }
            else {
                var matches = /^function\s*([^(\s]*)/.exec(fn.toString());
                if (matches && matches.length > 0) { return matches[1]; }
            }
        },
        
        /**
         * Shorthand for getElementById
         * "Pro JavaScript Techniques" (Resig, 2006 Apress)
         * @param name {String} The ID of the element to get
         * @return {HTMLElement} The element object
         */
        id: function (name) {
            return document.getElementById(name);
        },
        
        namespace: function (name) {
            var i, segs = name.split('.'), len = segs.length, seg, last = window;
            for (i = 0; i < len; i++) {
                seg = segs[i];
                last = last[seg] = last[seg] || {};
            }
            return last;
        },

        /**
         * Prepends content to the inside of the given element
         * @param content {String} Content to prepend
         * @param elem {HTMLElement} The element to prepend html into
         */
        prepend: function (content, elem) {
            elem.innerHTML = content + elem.innerHTML;
        },
        
        /**
         * Purges references in the given DOM element that cause memory leaks in
         * IE. Should be called before removing any element, either by the
         * removeChild method, or by setting the innerHTML property.
         * See http://javascript.crockford.com/memory/leak.html
         * @param domElem {HTMLElement}
         */
        purge: function (domElem) {
            var a = domElem.attributes, i, l, n;
            if (a) {
                l = a.length;
                for (i = 0; i < l; i += 1) {
                    n = a[i].name;
                    if (typeof domElem[n] === 'function') {
                        domElem[n] = null;
                    }
                }
            }
            a = domElem.childNodes;
            if (a) {
                l = a.length;
                for (i = 0; i < l; i += 1) {
                    this.purge(domElem.childNodes[i]);
                }
            }
        },        

        /**
         * Shorthand for getElementsByTagName
         * "Pro JavaScript Techniques" (Resig, 2006 Apress)
         * @param name {String} The ID of the element to get
         * @param [elem] {HTMLElement} Optional element to scope search
         * @return {Array} The matching elements
         */
        tag: function (name, elem) {
            return (elem || document).getElementsByTagName(name);
        },

        /**
         * Thanks Prototype :)
         * @param html {Object}
         */
        unescapeHtml: function (html) {
            var div = document.createElement('div');
            div.innerHTML = html.replace(/<\/?[^>]+>/gi, '').replace(/&apos;/g,"'");
            return div.childNodes[0].nodeValue;
        },

        /**
         * Version String
         */
        version: "EK @ek.version@",
		
        /**
         * Writes an object to the Firebug warn console, if it exists. 
         * @param obj {Object} The object to write to the console
         */
        warn: function (obj) {
            if (window.console && console.warn) { console.warn(obj); }
        }
    };
} else {
    throw("What th'EK?! 'EK' namespace conflict.");
}
